package org.metasketch.diagram.javafx.graphics;

import java.util.ArrayList;
import java.util.List;

import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Parent;
import javafx.scene.input.MouseEvent;

import org.metasketch.editor.links.ILink;
import org.metasketch.editor.links.LineSection;
import org.metasketch.editor.toolbox.ISelectable;
import org.metasketch.graphics.BaseGraphic;
import org.metasketch.graphics.Diagram;
import org.metasketch.graphics.GraphicContainer;
import org.metasketch.graphics.GraphicLink;
import org.metasketch.javafx.graphics.IJFXGraphicNode;
import org.metasketch.javafx.graphics.JFXDiagram;
import org.metasketch.model.BaseModel;
import org.metasketch.model.CommonIdentified;
import org.metasketch.model.ModelChangeManager;

public abstract class BaseLink extends Group implements IJFXGraphicNode,
		ISelectable, EventHandler<MouseEvent> {

	protected List<LineSection> lines = new ArrayList<LineSection>();
	// Line line = new Line();

	protected CommonIdentified semantic;
	protected GraphicLink graphicLink;
	protected ILink link;

	protected SelectLine selectLine = new SelectLine(this);
	protected ModelChangeManager modelChangeManager;
	protected org.metasketch.diagram.javafx.graphics.BaseGraphic source;
	protected org.metasketch.diagram.javafx.graphics.BaseGraphic target;

	public BaseLink(GraphicLink graphicLink) {
		this.graphicLink = graphicLink;

		// getChildren().add(line);
		setTranslateX(0);
		setTranslateY(0);

	}

	@Override
	public BaseGraphic getGraphicNode() {
		return graphicLink;
	}

	public CommonIdentified getSemantic() {
		return semantic;
	}

	@Override
	public void setup(BaseGraphic graphic, CommonIdentified semantic,
			Diagram diagram, BaseModel model) {
		graphicLink = (GraphicLink) graphic;
		setup(semantic, diagram, model);
	}

	public void setup(CommonIdentified semantic, Diagram diagram,
			BaseModel model) {
		this.semantic = semantic;

		continueSetup();

		// resizeGraphic();
		setSemantic(semantic);
	}

	protected abstract void continueSetup();

	public abstract void refreshLineDecorations();

	public void setSelected(boolean selected) {
		selectLine.setSelected(selected);
	}

	// public void setPosition(double x2, double y2) {
	//
	// }

	// protected abstract void resizeGraphic();

	@Override
	public void modelChanged(CommonIdentified semantic) {
		// setSemantic(semantic);
		refreshModelGraphic();
		// if(source != null && semantic == source.getSemantic())
		// {
		// target.modelChanged(semantic);
		// }

	}

	private void setSemantic(CommonIdentified semantic) {
		this.semantic = semantic;
		refreshModelGraphic();
	}

	protected abstract void refreshModelGraphic();

	public void setModelChangeManager(ModelChangeManager modelChangeManager) {
		this.modelChangeManager = modelChangeManager;
	}

	public void alertModelChanged() {
		if (modelChangeManager == null)
			return;

		modelChangeManager.alertChanges(semantic);
		if (source != null)
			modelChangeManager.alertChanges(source.getSemantic());
		if (target != null)
			modelChangeManager.alertChanges(target.getSemantic());
	}

	public ILink getLink() {
		return link;
	}

	public void setLink(ILink link) {
		this.link = link;
	}

	public void setSource(
			org.metasketch.diagram.javafx.graphics.BaseGraphic source) {

		this.source = source;

		if (source != null)
			graphicLink.setSource(source.getGraphicNode().getId());

		// if (source == null)
		// graphicLink.getPoints().add(new Point((int) startX, (int) startY));

		// line.setStartX(startX);
		// line.setStartY(startY);

	}

	public void setTarget(
			org.metasketch.diagram.javafx.graphics.BaseGraphic target) {

		this.target = target;

		if (target != null)
			graphicLink.setTarget(target.getGraphicNode().getId());

		// if (target == null)
		// graphicLink.getPoints().add(new Point((int) endX, (int) endY));

		// line.setEndX(endX);
		// line.setEndY(endY);

	}

	public List<LineSection> getLines() {

		// List<Line> lines = new ArrayList<Line>();
		// lines.add(line);

		return lines;
	}

	public boolean isSelected() {
		return selectLine.isSelected();
	}

	public LineSection getFirstSection() {
		return lines.get(0);
	}

	public LineSection getLastSection() {
		return lines.get(lines.size() - 1);
	}

	public org.metasketch.diagram.javafx.graphics.BaseGraphic getSource() {
		return source;
	}

	public org.metasketch.diagram.javafx.graphics.BaseGraphic getTarget() {
		return target;
	}

	@Override
	public void addedMainNode(CommonIdentified semantic) {
		// TODO Auto-generated method stub

	}

	@Override
	public void removedMainNode(CommonIdentified semantic) {
		// TODO Auto-generated method stub
		if (semantic == this.semantic)
			removeFromDiagram();
	}

	public void removeFromDiagram() {
		JFXDiagram diagram = getDiagram();

		diagram.getDiagram().getGraphics().remove(graphicLink);
		diagram.removeNode(this);

		// remove from target and source graphics..

		if (source != null)
			source.unregisterLink((DefaultLink) this);

		if (target != null)
			target.unregisterLink((DefaultLink) this);

	}

	public JFXDiagram getDiagram() {
		Parent parent = getParent();
		if (parent instanceof Group)
			return (JFXDiagram) parent.getParent().getParent().getParent()
					.getParent();

		return null;
	}

	@Override
	public ModelChangeManager getModelChangeManager() {
		return modelChangeManager;
	}

}
